package com.ming_za.sokoban.block;

import com.ming_za.sokoban.network.NetworkUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.DustParticleOptions;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import java.util.ArrayList;
import java.util.List;

/**
 * 终点方块
 */
public class EndBlock extends Block {

    public static final BooleanProperty POWERED = BlockStateProperties.POWERED;

    public EndBlock(Properties properties) {
        super(properties);
        registerDefaultState(this.defaultBlockState().setValue(POWERED,false));
    }

    @Override
    protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
        super.createBlockStateDefinition(builder);
        builder.add(POWERED);

    }

    @Override
    public void neighborChanged(BlockState blockState, Level level, BlockPos pos, Block block, BlockPos neighbor, boolean result) {

        //当旁边方块更新时判断是否为终点方块，避免循环执行导致内存溢出
        if (level.getBlockState(neighbor).getBlock() instanceof EndBlock){
            return;
        }

        if (checkNeighbor(level,pos)){

            //当周围更新的方块为“箱子方块”时
            if (level.getBlockState(neighbor).getBlock() instanceof BoxBlock){

                //播放音频
                level.playSound(null,neighbor, SoundEvents.ANVIL_LAND, SoundSource.BLOCKS,0.3F,1.0F);

                level.setBlock(neighbor,level.getBlockState(neighbor).setValue(BoxBlock.HOMING,true),3);
                //生成粒子,标出箱子方块棱边
                addParticle(neighbor);
                NetworkUtils.getInstance().updateParticle(neighbor,pos);


            }

            level.setBlock(pos,blockState.setValue(POWERED,true),3);
            level.updateNeighborsAt(pos,this);


        }else {
            if(blockState.getValue(POWERED)){
                level.setBlock(pos,blockState.setValue(POWERED,false),3);
                level.updateNeighborsAt(pos,this);
            }

        }

    }

    //粒子坐标运算===========================
    private double calculateX(int count){
        return count < 5 ? count * 0.2 : count < 10 ? 1 : count < 15 ? 1 - ((count - 10) * 0.2) : 0;
    }
    private double calculateZ(int count){
        return count < 5 ? 0 : count < 10 ? (count - 5) * 0.2 : count < 15 ? 1 : 1 - ((count - 15) * 0.2);
    }
    //=====================================

    //产生单个粒子
    private void spawnParticle(double x ,double y, double z){

        assert Minecraft.getInstance().level != null;
        Minecraft.getInstance().level.addParticle(DustParticleOptions.REDSTONE,x,y,z,0.0D,0.0D,0.0D);
    }

    //生成粒子
    public void addParticle(BlockPos pos){

        for (int i = 0; i < 48 ; i++){

            if (i < 20){
                //最顶部粒子
                double x = calculateX(i);
                double z = calculateZ(i);
                spawnParticle(pos.getX() + x,pos.getY() + 1,pos.getZ() + z);
            }else if (i < 28){
                //侧边棱粒子
                int j = i - 20;
                double yx = j % 2;
                double yy = ((j >> 1) + 1) * 0.2;
                for (int k = 0 ; k < 2 ; k++){
                    spawnParticle(pos.getX() + yx,pos.getY() + yy,pos.getZ() + k);
                }
            }else {
                //底部粒子
                int l = i - 28;
                double zx = calculateX(l);
                double zz = calculateZ(l);
                spawnParticle(pos.getX() + zx,pos.getY(),pos.getZ() + zz);
            }

        }
    }

    /**
     * 检测相邻方块是否为“箱子方块”，当存在“箱子方块”时返回true
     */
    private boolean checkNeighbor(Level level,BlockPos pos){

        List<BlockPos> posList = new ArrayList<>();
        posList.add(pos.east());
        posList.add(pos.west());
        posList.add(pos.south());
        posList.add(pos.north());
        posList.add(pos.above());
        posList.add(pos.below());

        for (BlockPos pos1 : posList){

            if ("block.sokoban.box_block".equals(level.getBlockState(pos1).getBlock().getDescriptionId())){
                return true;
            }
        }
        return false;

    }
    @Override
    public int getSignal(BlockState blockState, BlockGetter blockGetter, BlockPos pos, Direction direction) {

        return blockState.getValue(POWERED) ? 15: 0;
    }

    @Override
    public boolean isSignalSource(BlockState p_60571_) {
        return true;
    }

}
